home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / iomon2.zip / IORPT.PAS < prev    next >
Pascal/Delphi Source File  |  1992-02-20  |  9KB  |  346 lines

  1. program IOReport;
  2.   {-Displays data from resident I/O monitor}
  3.  
  4. uses
  5.   Dos,
  6.   OpString;
  7.  
  8. const
  9.   {For communicating with resident IOMON}
  10.   IoMonInt     = $61;
  11.   BufferSize   = 8192;
  12.   Output       = $10;
  13.   ContainsData = $80;
  14.  
  15.   {For building reports}
  16.   DirectionText : array[Boolean] of String[3] = ('In ', 'Out');
  17.   PageSize     = 60;
  18.   MaxTraceCol : Byte = 78;
  19.  
  20.   {Program options}
  21.   DoDetails    : Boolean = False;
  22.   DoTrace      : Boolean = False;
  23.   FileName     : PathStr = 'IORPT';
  24.  
  25. type
  26.   Buffer = record
  27.     IoAttr : Byte;
  28.     IoPort : Word;
  29.     IoData : Word;
  30.   end;
  31.   BufferArray = array[1..8192] of Buffer;
  32.   BufferPtr = ^BufferArray;
  33.  
  34.   OS = record
  35.     O : Word;
  36.     S : Word;
  37.   end;
  38.  
  39. var
  40.   Buf : BufferPtr;           {Pointer to IOMON's data}
  41.   Vector : Pointer;          {For checking for presence of IOMON}
  42.   I : Word;                  {Index}
  43.   Limit : Word;              {Highest possible index}
  44.   Regs : Registers;          {For getting pointer to Buf}
  45.   BaseAddr : Word;           {Base address of monitored UART}
  46.   Direction : Boolean;       {Direction of IO operation (in or out)}
  47.   IoAddr : Word;             {Address of IO operation}
  48.   IoReg : Word;              {UART register of IO operation}
  49.   DLab : Boolean;            {Boolean to track state of DLAB bit}
  50.   Lines : Word;              {For displaying headers}
  51.   Wrapped : Boolean;         {True if IOMON buffer wrapped once}
  52.   Head : Word;               {Head pointer of IOMON's buffer}
  53.   T : Text;
  54.  
  55.   procedure Abort(Msg : String; Code : Word);
  56.   begin
  57.     Write(Msg);
  58.     if Code <> 0 then
  59.       WriteLn(Code)
  60.     else
  61.       WriteLn;
  62.     Halt(Code);
  63.   end;
  64.  
  65.   procedure WriteHelp;
  66.     {-Write help and halt}
  67.   begin
  68.     WriteLn('Usage: IORPT [options]');
  69.     WriteLn('  /T      build standard APRO trace to IORPT.TRC');
  70.     WriteLn('  /D      build detailed audit report to IORPT.AUD');
  71.     WriteLn('  /F      filename to use (no extension)');
  72.     Halt;
  73.   end;
  74.  
  75.   procedure ParseCommandLine;
  76.     {-Gets command line options and sets various parameters.}
  77.   var
  78.     Code : Word;
  79.     Param : String;
  80.     Cnt : Word;
  81.  
  82.   begin
  83.     {Scan command line}
  84.      if ParamCount = 0 then
  85.       WriteHelp;
  86.     Param := ParamStr(1);
  87.     Cnt := 2;
  88.  
  89.     while True do begin
  90.       case Param[1] of
  91.         '/', '-' :
  92.           if Length(Param) <> 2 then
  93.             Abort('Invalid parameter: '+Param, 0)
  94.           else
  95.             case Upcase(Param[2]) of
  96.               'T' : DoTrace := True;
  97.               'D' : DoDetails := True;
  98.               else
  99.                 Abort('Invalid parameter: '+Param, 0);
  100.             end;
  101.       end;
  102.  
  103.       {Get next parameter}
  104.       if Cnt > ParamCount then
  105.         Exit;
  106.       Param := ParamStr(Cnt);
  107.       Inc(Cnt);
  108.     end;
  109.   end;
  110.  
  111.   function ShowByte(W : Word) : String;
  112.   begin
  113.     if (W > 31) and (W < 127) then
  114.       ShowByte := '  [' + Char(Lo(W)) + ']'
  115.     else
  116.       ShowByte := '';
  117.   end;
  118.  
  119.   procedure BuildDetailReport;
  120.   begin
  121.     {Open the report file}
  122.     Assign(T, Filename + '.AUD');
  123.     Rewrite(T);
  124.  
  125.     if Wrapped then begin
  126.       I := (Head div SizeOf(Buffer)) + 1;
  127.       Limit := Head;
  128.     end else begin
  129.       I := 1;
  130.       Limit := BufferSize div SizeOf(Buffer);
  131.     end;
  132.  
  133.     Lines := PageSize;
  134.     while (I <> Limit) and ((Buf^[I].IoAttr and ContainsData) = ContainsData) do begin
  135.  
  136.       {Write headings}
  137.       Inc(Lines);
  138.       if Lines > PageSize then begin
  139.         WriteLn(T);
  140.         WriteLn(T, ' Addr  Direction  Value   Message');
  141.         WriteLn(T, ' ----  ---------  -----   -------');
  142.         Lines := 1;
  143.       end;
  144.  
  145.       {Report one line of data}
  146.       Direction := Buf^[I].IoAttr and Output = Output;
  147.       IoAddr := Buf^[I].IoPort;
  148.       Write(T, ' ', HexW(IoAddr), '     ');
  149.       Write(T, DirectionText[Direction], '       ');
  150.       Write(T, HexB(Lo(Buf^[I].IoData)), '    ');
  151.  
  152.       {Set BaseAddr first time thru}
  153.       if BaseAddr = 0 then
  154.         case IoAddr of
  155.           $3F8..$3FF : BaseAddr := $3F8;
  156.           $2F8..$2FF : BaseAddr := $2F8;
  157.           $3E8..$3EF : BaseAddr := $3E8;
  158.           $2E8..$2EF : BaseAddr := $2E8;
  159.         end;
  160.  
  161.       {Show a text message}
  162.       IoReg := IoAddr - BaseAddr;
  163.       case IoReg of
  164.         0 : if DLab then
  165.               if Direction then
  166.                 WriteLn(T, 'Setting baud rate')
  167.               else
  168.                 WriteLn(T, 'Reading baud rate')
  169.             else
  170.               if Direction then
  171.                 WriteLn(T, 'Output byte', ShowByte(Buf^[I].IoData))
  172.               else
  173.                 WriteLn(T, 'Input byte', ShowByte(Buf^[I].IoData));
  174.         1 : if Direction then
  175.               WriteLn(T, 'Setting interrupt enable mask')
  176.             else
  177.               WriteLn(T, 'Reading interrupt enable mask');
  178.         2 : if Direction then
  179.               if Buf^[I].IoData and $01 = $01 then
  180.                 WriteLn(T, 'Enabling FIFO')
  181.               else
  182.                 WriteLn(T, 'Disabling FIFO')
  183.             else
  184.               WriteLn(T, 'Reading interrupt type');
  185.         3 : if Direction then
  186.               if Buf^[I].IoData and $80 = $80 then begin
  187.                 WriteLn(T, 'Enabling DLAB');
  188.                 DLab := True;
  189.               end else begin
  190.                 WriteLn(T, 'Setting line control register (DLAB off)');
  191.                 DLab := False;
  192.               end
  193.             else
  194.               WriteLn(T, 'Reading line control register');
  195.         4 : if Direction then
  196.               WriteLn(T, 'Setting modem control register')
  197.             else
  198.               WriteLn(T, 'Reading modem control register');
  199.         5 : if not Direction then
  200.               WriteLn(T, 'Reading line status register')
  201.             else
  202.               WriteLn(T);
  203.         6 : if not Direction then
  204.               WriteLn(T, 'Reading modem status register')
  205.             else
  206.               WriteLn(T);
  207.         7 : if Direction then
  208.               WriteLn(T, 'Writing scratch register')
  209.             else
  210.               WriteLn(T, 'Reading scratch register');
  211.       end;
  212.       Inc(I);
  213.       if I > BufferSize div SizeOf(Buffer) then
  214.         I := 1;
  215.     end;
  216.  
  217.     Close(T);
  218.   end;
  219.  
  220.   procedure BuildTraceReport;
  221.     {-Write a standard APRO trace report}
  222.   var
  223.     Col : Byte;
  224.     OldDirection : Boolean;
  225.     C : Char;
  226.     J : Word;
  227.  
  228.     procedure CheckCol(N : Byte);
  229.       {-Wrap if N bytes would exceed column limit}
  230.     begin
  231.       Inc(Col, N);
  232.       if Col > MaxTraceCol then begin
  233.         WriteLn(T);
  234.         Col := N;
  235.       end;
  236.     end;
  237.  
  238.   begin
  239.     {Open the report file}
  240.     Assign(T, Filename + '.TRC');
  241.     Rewrite(T);
  242.  
  243.     DLab := False;
  244.     Col := 1;
  245.  
  246.     if Wrapped then begin
  247.       I := (Head div SizeOf(Buffer)) + 1;
  248.       Limit := Head;
  249.     end else begin
  250.       I := 1;
  251.       Limit := BufferSize div SizeOf(Buffer);
  252.     end;
  253.  
  254.     while (I <> Limit) and ((Buf^[I].IoAttr and ContainsData) = ContainsData) do begin
  255.  
  256.       {Get the next entry}
  257.       Direction := Buf^[I].IoAttr and Output = Output;
  258.       IoAddr := Buf^[I].IoPort;
  259.  
  260.       {Set BaseAddr first time thru}
  261.       if BaseAddr = 0 then begin
  262.         case IoAddr of
  263.           $3F8..$3FF : BaseAddr := $3F8;
  264.           $2F8..$2FF : BaseAddr := $2F8;
  265.           $3E8..$3EF : BaseAddr := $3E8;
  266.           $2E8..$2EF : BaseAddr := $2E8;
  267.         end;
  268.         OldDirection := not Direction;
  269.       end;
  270.  
  271.       {Show only puts and gets}
  272.       if IoAddr = BaseAddr then begin
  273.         if Direction <> OldDirection then begin
  274.           OldDirection := Direction;
  275.           if Direction then
  276.             WriteLn(T, ^M^J^M^J'Transmit:')
  277.           else
  278.             WriteLn(T, ^M^J^M^J'Receive:');
  279.         end;
  280.  
  281.         {Display this character}
  282.         if not DLab then begin
  283.           C := Char(Lo(Buf^[I].IoData));
  284.           if (Ord(C) < 32) or (Ord(C) > 126) then begin
  285.             if Ord(C) > 99 then
  286.               J := 5
  287.             else if Ord(C) > 9 then
  288.               J := 4
  289.             else
  290.               J := 3;
  291.             CheckCol(J);
  292.             Write(T, '[',Ord(C),']')
  293.           end else begin
  294.             CheckCol(1);
  295.             Write(T, C);
  296.           end;
  297.         end;
  298.       end else
  299.         {Track DLAB}
  300.         if IoAddr - BaseAddr = 3 then
  301.           if Direction then
  302.             if Buf^[I].IoData and $80 = $80 then
  303.               DLab := True
  304.             else
  305.               DLab := False;
  306.       Inc(I);
  307.       if I > BufferSize div SizeOf(Buffer) then
  308.         I := 1;
  309.     end;
  310.  
  311.     Close(T);
  312.   end;
  313.  
  314. begin
  315.   ParseCommandLine;
  316.  
  317.   {Assure IOMON is resident}
  318.   GetIntVec(IoMonInt, Vector);
  319.   if Vector = nil then begin
  320.     WriteLn('IoMon not installed');
  321.     Halt(1);
  322.   end;
  323.  
  324.   {Inits}
  325.   DLab := False;
  326.   BaseAddr := 0;
  327.  
  328.   {Get buffer address from IOMON}
  329.   Intr(IoMonInt, Regs);
  330.   with Regs do begin
  331.     OS(Buf).S := Regs.DX;
  332.     OS(Buf).O := Regs.BX;
  333.     Wrapped := Regs.AX = 1;
  334.     Head := Regs.CX;
  335.   end;
  336.  
  337.   if DoDetails then
  338.     BuildDetailReport;
  339.  
  340.   if DoTrace then
  341.     BuildTraceReport;
  342. end.
  343.  
  344.  
  345.  
  346.